/*
Copyright 2010  Murali Devi (profdevi@gmail.com)

This file is part of ComineGL Project.

ComineGL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

ComineGL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with ComineGL.  If not, see <http://www.gnu.org/licenses/>.

This code uses the irrlicht and irrklang libraries.  Please read
the libraries copyrights at 

	irrlicht library:  http://irrlicht.sourceforge.net
	irrklang library:  http://www.ambiera.com/irrklang

*/



//v0.16 copyright Comine.com 20110925U18
#include "MStdLib.h"
#include "Global.h"
#include "ComineGL.h"


//**********************************************************
//** Module Elements
//**********************************************************
static bool GOnRawKeyPress(int keycode,void *extra)
	{
	bool (*keyhandler)(int);
	keyhandler=(bool (*)(int))extra;
	if(keyhandler==NULL)
		{
		return true; 
		}

	keyhandler(keycode);
	return true;
	}


//**********************************************************
//** CGLFunctions
//**********************************************************
MDLLFUN const char *CGLGetVersion(void)
	{
	return GlobalVersion;
	}


//////////////////////////////////////////////
MDLLFUN  bool CGLCreate(int width,int height,int bpp,bool fullscreen)
	{
	CGLDestroy();

	//Auto Select Correct Dimensions
	if(fullscreen==true)
		{
		if(!(width==320 && height==240)
				&& !(width==640 && height==480)
				&& !(width==800 && height==600)
				&& !(width==1024 && height==768)
				&& !(width==1152 && height==864)
				&& !(width==1280 && height==1024)
				&& !(width==1600 && height==1200) )
			{
			width=800;
			height=600;
			MStdPrintf("Auto Selecting Screen Size %dx%d\n",width,height);
			}
		}

	// Autoselect bits per pixel
	if(bpp!=16 && bpp!=32 && bpp!=24)
		{
		bpp=32;
		MStdPrintf("Auto Selecting to %d Bits Per Pixel\n",bpp);
		}
	
	if(GlobalCreate(width,height,bpp,fullscreen)==false)
		{
		MStdPrintf("**Unable to init Global Block\n");
		return false;
		}

	// Load up the Irrklang Device
	// Init IrrKlang Device
	GlobalRefSoundDevice=createIrrKlangDevice();
	if(GlobalRefSoundDevice==NULL)
		{
		MStdPrintf("**Unable to init IrrKlangDevice\n");
		CGLDestroy();
		return false;
		}	

	// Turn off mouse
	GlobalRefCursorControl->setVisible(false);
	
	return true;
	}


///////////////////////////////////////////////////////////
MDLLFUN  bool CGLDestroy(void)
	{
	if(GlobalInitialized==false)
		{
		// Already Uninitialized
		return true;
		}

	GlobalDestroy();
	return true;
	}


////////////////////////////////////////////////////////////
MDLLFUN bool CGLGameLoop(void)
	{
	if(GlobalInitialized==false)
		{
		return false;
		}

	// Standard Game Loop
	for( ; ; )
		{
		// Capture F12 Key for status
		if(GlobalEventInput.IsKeyPressed(CGL_KEY_F12)==true)
			{
			CGLPrintStatus();
			}

		// If Game Loop Exit is called break loop
		if(GlobalGameLoopBreakFlag==true)
			{
			// Reset GlobalGameLoopExitFlag
			GlobalGameLoopBreakFlag=false;

			// Since we are exiting the game loop by a request from API,
			// we will return with true.
			return true;
			}

		unsigned int realtime=GlobalRefDevice->getTimer()->getRealTime();

		// Process Input
		GlobalEventInput.UpdateTime();

		// Update Task Managers
		GlobalTaskQueueInternal.ProcessEvents(realtime);
		GlobalTaskQueue.ProcessEvents(realtime);
		
		if(GlobalRefDevice->run()==false)
			{
			// User exited with Alt-F4
			// So we will return with false too.
			return false;
			}

		//**Rendering Secion
		GlobalRefVideoDriver->beginScene(true,true,GlobalBackColor);

		// If Back Render is set, render the background
		if(GlobalWindowBackRenderer!=NULL)
			{
			if(GlobalWindowBackRenderer()==false)
				{
				GlobalWindowBackRenderer=NULL;
				}
			}

		// Draw the scene graph
		GlobalRefSceneMgr->drawAll();

		// if front render is set, render the front
		if(GlobalWindowFrontRenderer!=NULL)
			{
			if(GlobalWindowFrontRenderer()==false)
				{
				GlobalWindowFrontRenderer=NULL;
				}
			}

		GlobalRefVideoDriver->endScene();
		}

	return true;
	}


////////////////////////////////////////////////////////////
MDLLFUN bool CGLGameLoopBreak(void)
	{
	MStdAssert(GlobalInitialized==true);
	GlobalGameLoopBreakFlag=true;
	return true;
	}


////////////////////////////////////////////////////////////
MDLLFUN bool CGLZipFileAdd(const char *zipfile)
	{
	if(GlobalInitialized==false)
		{
		return false;
		}
	
	if(GlobalRefFileSystem->addZipFileArchive(zipfile)==false)
		{
		MStdPrintf("Unable to add zip file %s\n",zipfile);
		return false;
		}

	return true;
	}


////////////////////////////////////////////////////////////
MDLLFUN bool CGLPrintStatus(void)
	{
	MStdPrintf("\n");
	MStdPrintf(	"*********************************\n"
				"*   ComineGL Engine Status       \n"
				"*********************************\n");

	if(GlobalInitialized==false)
		{
		MStdPrintf("\t**Engine is not initialized\n\n");
		return true;
		}

	MStdPrintf("\tNode Count      : %d\n",GlobalNodeList.GetCount() );
	MStdPrintf("\tMesh Count      : %d\n",GlobalMeshList.GetCount() );
	MStdPrintf("\tTexture Count   : %d\n",GlobalTextureList.GetCount() );
	MStdPrintf("\tFont Count      : %d\n",GlobalFontList.GetCount() );
	MStdPrintf("\tSound Count     : %d\n",GlobalSoundList.GetCount() );
	MStdPrintf("\tAnimation Count : %d\n",GlobalAnimationList.GetCount() );
	MStdPrintf("\tInt Array Count : %d\n",GlobalIntArrayList.GetCount() );
	MStdPrintf("\tTask Count      : %d\n",GlobalTaskQueue.GetEventCount() );
	MStdPrintf("\tInternal Tasks  : %d\n",GlobalTaskQueueInternal.GetEventCount() );
	MStdPrintf("\tTriangle Sets   : %d\n",GlobalTrisetList.GetCount() );
	MStdPrintf("\tFrames Per Sec  : %d\n",int(GlobalRefVideoDriver->getFPS()) );
	MStdPrintf("\n");

	return true;
	}


////////////////////////////////////////////////////////////
MDLLFUN bool CGLKeyboardSetHandler(bool keyboardhandler(int) )
	{
	if(GlobalInitialized==false)
		{
		return false;
		}

	if(keyboardhandler==NULL)
		{
		GlobalEventInput.SetKeyboardHandler(0,0);
		MStdPrintf("Cleared Keyboard Handler\n");
		}
	else
		{
		GlobalEventInput.SetKeyboardHandler(GOnRawKeyPress,keyboardhandler);
		MStdPrintf("Set a Keyboard Handler\n");
		}
	
	return true;
	}


////////////////////////////////////////////////////////////
MDLLFUN unsigned int CGLTimeGet(void)
	{
	if(GlobalInitialized==false)
		{
		return false;
		}
	
	return GlobalRefDevice->getTimer()->getTime();
	}

